#include "server.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mysql/mysql.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <time.h>

#define BUFFER_SIZE 1024
#define MAX_PATH_LEN 256

MYSQL *conn = NULL;

/* 密码哈希函数 */
char* my_hash_password(const char *password) {
    static char hashed[128];
    snprintf(hashed, sizeof(hashed), "HASHED_%s", password);
    return hashed;
}

/* 命令解析函数 */
void parse_command(char *buffer, char **cmd, char **user, char **dir, char **arg) {
    *cmd = strtok(buffer, " ");
    *user = strtok(NULL, " ");
    *dir = strtok(NULL, " ");
    *arg = strtok(NULL, " ");
    
    if (*arg) {
        char *extra = strtok(NULL, "\n");
        if (extra) {
            strcat(*arg, " ");
            strcat(*arg, extra);
        }
    }
}

/* 用户认证 */
int authenticate_user(const char *username, const char *password) {
    char query[512];
    char *hashed_pw = my_hash_password(password);
    
    snprintf(query, sizeof(query), 
        "SELECT id FROM users WHERE username='%s' AND password='%s'", 
        username, hashed_pw);
    
    if (mysql_query(conn, query)) 
        return 0;

    MYSQL_RES *res = mysql_store_result(conn);
    int valid = (mysql_num_rows(res) > 0);
    mysql_free_result(res);
    return valid;
}

/* 用户注册 */
int register_user(const char *username, const char *password) {
    char query[512];
    char *hashed_pw = my_hash_password(password);
    
    snprintf(query, sizeof(query),
        "INSERT INTO users (username, password) VALUES ('%s', '%s')", 
        username, hashed_pw);
        
    if (mysql_query(conn, query)) {
        return 0;
    }
    
    // 创建用户目录
    char user_dir[MAX_PATH_LEN];
    snprintf(user_dir, MAX_PATH_LEN, "%s%s", USER_DIR_PREFIX, username);
    mkdir(user_dir, 0700);
    
    return 1;
}

/* 创建目录 */
int create_directory(int user_id, const char *dirname, int parent_id) {
    char query[512];
    snprintf(query, sizeof(query),
        "INSERT INTO directories (user_id, name, parent_id) VALUES (%d, '%s', %d)",
        user_id, dirname, parent_id);
        
    return (mysql_query(conn, query) == 0);
}

/* 获取完整路径 */
char* get_full_path(int user_id, int directory_id, const char *filename) {
    static char path[MAX_PATH_LEN];
    
    if (directory_id == 0) {
        snprintf(path, MAX_PATH_LEN, "%s%d/%s", USER_DIR_PREFIX, user_id, filename);
    } else {
        char query[512];
        snprintf(query, sizeof(query),
            "SELECT CONCAT(d.name, '/') FROM directories d WHERE d.id = %d",
            directory_id);
            
        if (mysql_query(conn, query) == 0) {
            MYSQL_RES *res = mysql_store_result(conn);
            MYSQL_ROW row = mysql_fetch_row(res);
            if (row) {
                snprintf(path, MAX_PATH_LEN, "%s%d/%s%s", USER_DIR_PREFIX, user_id, row[0], filename);
            }
            mysql_free_result(res);
        }
    }
    
    return path;
}

/* 文件上传处理 */
void handle_upload(int sockfd, const char *username, const char *filename, long file_size, int directory_id) {
    // 获取用户ID
    char query[512];
    snprintf(query, sizeof(query), "SELECT id FROM users WHERE username='%s'", username);
    if (mysql_query(conn, query)) {
        send_response(sockfd, "ERROR", "数据库查询失败");
        return;
    }
    
    MYSQL_RES *res = mysql_store_result(conn);
    if (!res) {
        send_response(sockfd, "ERROR", "获取用户ID失败");
        return;
    }
    
    MYSQL_ROW row = mysql_fetch_row(res);
    if (!row) {
        mysql_free_result(res);
        send_response(sockfd, "ERROR", "用户不存在");
        return;
    }
    
    int user_id = atoi(row[0]);
    mysql_free_result(res);
    
    // 创建用户目录结构
    char user_root[MAX_PATH_LEN];
    snprintf(user_root, MAX_PATH_LEN, "%s%d", USER_DIR_PREFIX, user_id);
    mkdir(user_root, 0700);
    
    // 构建完整路径
    char full_path[MAX_PATH_LEN];
    if (directory_id == 0) {
        snprintf(full_path, MAX_PATH_LEN, "%s/%s", user_root, filename);
    } else {
        // 查询目录路径
        snprintf(query, sizeof(query),
            "SELECT name FROM directories WHERE id=%d AND user_id=%d",
            directory_id, user_id);
            
        if (mysql_query(conn, query)) {
            send_response(sockfd, "ERROR", "目录查询失败");
            return;
        }
        
        res = mysql_store_result(conn);
        row = mysql_fetch_row(res);
        if (!row) {
            mysql_free_result(res);
            send_response(sockfd, "ERROR", "目录不存在");
            return;
        }
        
        char dir_path[MAX_PATH_LEN];
        snprintf(dir_path, MAX_PATH_LEN, "%s/%s", user_root, row[0]);
        mkdir(dir_path, 0700);
        snprintf(full_path, MAX_PATH_LEN, "%s/%s", dir_path, filename);
        mysql_free_result(res);
    }
    
    // 发送准备就绪信号
    send_response(sockfd, "READY", "准备接收文件");
    printf("尝试打开的路径：%s\n", full_path); // input_path 是实际传给 fopen 的字符串
    // 接收文件内容
    FILE *file = fopen(full_path, "wb");
    if (!file) {
        send_response(sockfd, "ERROR", "文件创建失败");
        return;
    }

    char buffer[BUFFER_SIZE];
    ssize_t bytes_received;
    long total_bytes = 0;

    while (total_bytes < file_size && 
          (bytes_received = read(sockfd, buffer, BUFFER_SIZE)) > 0) {
        fwrite(buffer, 1, bytes_received, file);
        total_bytes += bytes_received;
    }

    fclose(file);
    
    // 修复SQL语句拼接错误
    snprintf(query, sizeof(query),
        "INSERT INTO files (user_id, directory_id, filename, storage_path, size) "
        "VALUES (%d, %d, '%s', '%s', %ld)",
        user_id, directory_id, filename, full_path, file_size);
    mysql_query(conn, query);
    
    send_response(sockfd, "SUCCESS", "文件上传完成");
}

/* 文件名安全检查 */
bool sanitize_filename(const char *filename, char *cleaned, size_t size) {
    if (!filename || !cleaned || size < 1) {
        return false;
    }
    
    const char *valid_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789._-";
    size_t len = strlen(filename);
    size_t cleaned_len = 0;
    
    // 防止文件名过长
    if (len >= size) {
        return false;
    }
    
    // 检查是否包含路径分隔符
    for (size_t i = 0; i < len; i++) {
        if (filename[i] == '/' || filename[i] == '\\' || filename[i] == '.') {
            // 只允许文件名中的最后一个点作为扩展名分隔符
            if (filename[i] == '.' && i != 0 && i != len - 1) {
                bool has_more_dots = false;
                for (size_t j = i + 1; j < len; j++) {
                    if (filename[j] == '.') {
                        has_more_dots = true;
                        break;
                    }
                }
                if (!has_more_dots) {
                    cleaned[cleaned_len++] = filename[i];
                    continue;
                }
            }
            return false;
        }
        
        // 检查是否为有效字符
        if (strchr(valid_chars, filename[i]) == NULL) {
            return false;
        }
        
        cleaned[cleaned_len++] = filename[i];
    }
    
    cleaned[cleaned_len] = '\0';
    return true;
}

/* 文件列表 */
void handle_list_files(int sockfd, const char *username, int directory_id) {
    char response[BUFFER_SIZE * 4] = {0};
    char query[1024];
    
    // 获取用户ID
    snprintf(query, sizeof(query), "SELECT id FROM users WHERE username='%s'", username);
    mysql_query(conn, query);
    MYSQL_RES *res = mysql_store_result(conn);
    MYSQL_ROW row = mysql_fetch_row(res);
    int user_id = atoi(row[0]);
    mysql_free_result(res);
    
    // 查询目录
    snprintf(query, sizeof(query),
        "SELECT id, name, parent_id FROM directories "
        "WHERE user_id=%d AND parent_id=%d", user_id, directory_id);
    mysql_query(conn, query);
    res = mysql_store_result(conn);
    
    strcat(response, "=== 目录列表 ===\n");
    while ((row = mysql_fetch_row(res))) {
        char dir_info[128];
        snprintf(dir_info, sizeof(dir_info), "[DIR] %s (ID:%s)\n", row[1], row[0]);
        strcat(response, dir_info);
    }
    mysql_free_result(res);
    
    // 查询文件
    snprintf(query, sizeof(query),
        "SELECT filename, size, created_at FROM files "
        "WHERE user_id=%d AND directory_id=%d", user_id, directory_id);
    mysql_query(conn, query);
    res = mysql_store_result(conn);
    
    strcat(response, "\n=== 文件列表 ===\n");
    while ((row = mysql_fetch_row(res))) {
        char file_info[256];
        snprintf(file_info, sizeof(file_info), "%-30s %-10s bytes %-20s\n", 
                row[0], row[1], row[2]);
        strcat(response, file_info);
    }
    mysql_free_result(res);
    
    strcat(response, "END_OF_LIST\n");
    write(sockfd, response, strlen(response));
}

/* 文件删除 */
void handle_delete_file(const char *username, const char *filename, int directory_id) {
    char query[512];
    
    // 获取用户ID
    snprintf(query, sizeof(query), "SELECT id FROM users WHERE username='%s'", username);
    mysql_query(conn, query);
    MYSQL_RES *res = mysql_store_result(conn);
    MYSQL_ROW row = mysql_fetch_row(res);
    int user_id = atoi(row[0]);
    mysql_free_result(res);
    
    // 获取文件路径
    snprintf(query, sizeof(query),
        "SELECT storage_path FROM files WHERE user_id=%d AND directory_id=%d AND filename='%s'",
        user_id, directory_id, filename);
    mysql_query(conn, query);
    res = mysql_store_result(conn);
    row = mysql_fetch_row(res);
    
    if (!row) {
        return;
    }
    
    char *filepath = row[0];
    unlink(filepath); // 删除物理文件
    
    // 删除数据库记录
    snprintf(query, sizeof(query),
        "DELETE FROM files WHERE user_id=%d AND directory_id=%d AND filename='%s'",
        user_id, directory_id, filename);
    mysql_query(conn, query);
    
    mysql_free_result(res);
}

/* 退出登录 */
void handle_logout(const char *username) {
    printf("用户 %s 已退出登录\n", username);
}

/* 发送响应 */
void send_response(int sockfd, const char *status, const char *message) {
    char response[512];
    snprintf(response, sizeof(response), "%s: %s\nEND_OF_RESPONSE\n", status, message);
    write(sockfd, response, strlen(response));
}

/* 客户端命令处理 */
void handle_client_commands(int client_sock, char *cmd, char *username, char *arg, int directory_id) {
    if (cmd == NULL) {
        send_response(client_sock, "ERROR", "无效命令");
        return;
    }

    if (strcmp(cmd, "REGISTER") == 0) {
        if (register_user(username, arg)) {
            send_response(client_sock, "SUCCESS", "注册成功");
        } else {
            send_response(client_sock, "ERROR", "注册失败");
        }
    } 
    else if (strcmp(cmd, "LOGIN") == 0) {
        if (authenticate_user(username, arg)) {
            send_response(client_sock, "SUCCESS", "登录成功");
        } else {
            send_response(client_sock, "ERROR", "认证失败");
        }
    }
    else if (strcmp(cmd, "UPLOAD") == 0) {
        char *filename = strtok(arg, " ");
        char *size_str = strtok(NULL, " ");
        long size = size_str ? atol(size_str) : 0;
        
        if (filename && size > 0) {
            handle_upload(client_sock, username, filename, size, directory_id);
        } else {
            send_response(client_sock, "ERROR", "无效的上传参数");
        }
    }
    else if (strcmp(cmd, "DOWNLOAD") == 0) {
        // 此处download函数需要实现
        send_response(client_sock, "ERROR", "下载功能暂未实现");
    }
    else if (strcmp(cmd, "LIST") == 0) {
        handle_list_files(client_sock, username, directory_id);
    }
    else if (strcmp(cmd, "DELETE") == 0) {
        handle_delete_file(username, arg, directory_id);
        send_response(client_sock, "SUCCESS", "文件删除成功");
    }
    else if (strcmp(cmd, "MKDIR") == 0) {
        // 获取用户ID
        char query[512];
        snprintf(query, sizeof(query), "SELECT id FROM users WHERE username='%s'", username);
        mysql_query(conn, query);
        MYSQL_RES *res = mysql_store_result(conn);
        MYSQL_ROW row = mysql_fetch_row(res);
        int user_id = atoi(row[0]);
        mysql_free_result(res);
        
        if (create_directory(user_id, arg, directory_id)) {
            send_response(client_sock, "SUCCESS", "目录创建成功");
        } else {
            send_response(client_sock, "ERROR", "目录创建失败");
        }
    }
    else if (strcmp(cmd, "LOGOUT") == 0) {
        handle_logout(username);
        send_response(client_sock, "SUCCESS", "已退出登录");
    }
}

/* 客户端主循环 */
void handle_client(int client_sock) {
    char buffer[BUFFER_SIZE];
    
    while (1) {
        ssize_t bytes_read = read(client_sock, buffer, BUFFER_SIZE - 1);
        if (bytes_read <= 0) break;
        
        buffer[bytes_read] = '\0';
        char *cmd, *username, *dir_id, *arg;
        int directory_id = 0;
        
        parse_command(buffer, &cmd, &username, &dir_id, &arg);
        directory_id = dir_id ? atoi(dir_id) : 0;
        
        handle_client_commands(client_sock, cmd, username, arg, directory_id);
    }
    
    close(client_sock);
}

/* 日志记录 */
void log_event(const char *event_type, const char *username, const char *details) {
    time_t now = time(NULL);
    struct tm *tm_info = localtime(&now);
    char timestamp[20];
    strftime(timestamp, 20, "%Y-%m-%d %H:%M:%S", tm_info);
    
    // 控制台输出
    printf("[%s][%s] %s: %s\n", timestamp, event_type, username ? username : "unknown", details);
    
    // 写入日志文件
    FILE *log_file = fopen("server.log", "a");
    if (log_file) {
        fprintf(log_file, "[%s][%s] %s: %s\n", timestamp, event_type, username ? username : "unknown", details);
        fclose(log_file);
    }
}